﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Spanner;

namespace SpannerWebSite
{
    internal partial class Home : CommonUI
    {
        internal static SpannerChapter TheChapter;

        static Home()
        {
            var sections = new List<SpannerSection> { };
            var initActs = new List<Act> { };

            // Write out files we're going to depend on here.  I know, I know, this is
            // very naughty in a static constructor...

            MemoryGame.WriteWebPage();
            LoginDemo.WriteWebPage();

            sections.Add(
                Section("Motivation", "Motivation",
                    UL(
                        LI("Do you wish you could develop web applications in a single language?"),
                        LI("Integrate variables and functions across HTML, CSS, JavaScript and POCOs?"),
                        LI("Do you wish errors (not just warnings) were indicated ", Em("as you code"), "?"),
                        LI("Do you wish you could fix bugs in seconds rather than minutes or hours?"),
                        LI("Do you wish you could do all this using your existing knowledge of CSS, HTML, and ",
                        "JavaScript?"),
                        LI("And maintain compatibility with third-party JavaScript libraries?")
                    ),
                    P("If you answered ", Em("yes"), " to all these questions, then ", Spanner, " is for you!")
                )
            );

            var loginDemoContent = LoginDemo.Content();
            var showingLoginDemoSrc = ObsVar<bool>("showingLoginDemoSrc", true);

            sections.Add(
                Section("ToDoMVC", "ToDoMVC",
                    P(A("Here").WithAttr("href", "../Demo/html/ToDoMVC.html"), " can be found the canonical ",
                    Spanner, " implementation of the ", A("todomvc.com").WithAttr("href", "http://todomvc.com"), " ",
                    "demonstration.  The source code can be found on the ", Spanner, " code site.")
                )
            );

            sections.Add(
                Section("A Simple Example: a log-in/sign-up dialogue", "LogInDemo",
                    P("In traditional style, we start with something to whet the appetite. ",
                    "Here is a simple log-in/sign-up dialogue:"),
                    loginDemoContent,
                    Button(Show(Cond<string>(showingLoginDemoSrc,
                            "Show HTML & JS generated by Spanner",
                            "Show Spanner source code")))
                        .KoClick(Set(showingLoginDemoSrc, !showingLoginDemoSrc)),
                    P("The reader is invited to scan the Spanner source code, with an eye to ",
                    "getting the gist, before examining the generated HTML and JavaScript ",
                    "to see how clean and traceable it is."),
                    FileFragmentFigure(
                        Group(Em("Log-in Demo"), " source code in ", Spanner, "."),
                        Lang.csharp, "../../Home.LoginDemo.cs", "", null,
                        ignoreUnindentedLines: false
                    ).KoVisible(showingLoginDemoSrc).WithAttr("style", "height: 20em"),
                    FileFragmentFigure(
                        Group(Em("Log-in Demo"), " web page generated by", Spanner, "."),
                        Lang.markup, Path.Combine(Const.DemoWebSitePath, "html", "LoginDemo.html"), "", null,
                        ignoreUnindentedLines: false,
                        filter: StripSpannerRuntimeFilter
                    ).KoVisible(!showingLoginDemoSrc).WithAttr("style", "height: 20em")
                )
            );

            var memoryGameContent = MemoryGame.Content();
            initActs.Add(memoryGameContent.InitAct);
            var showingMemoryGameSrc = ObsVar<bool>("showingMemoryGameSrc", true);

            sections.Add(
                Section("A Non-trivial Example: the Memory Game", "ANonTrivialExample",
                    P("Here is something slightly more exciting..."),
                    memoryGameContent.BodyHtml,
                    Button(Show(Cond<string>(showingMemoryGameSrc,
                            "Show HTML & JS generated by Spanner",
                            "Show Spanner source code")))
                        .KoClick(Set(showingMemoryGameSrc, !showingMemoryGameSrc)),
                    P("Observe again the close correspondence between the ", Spanner, " implementation ",
                    "and the generated HTML and JavaScript."),
                    FileFragmentFigure(
                        Group(Em("Memory Game"), " source code in ", Spanner, "."),
                        Lang.csharp, "../../Home.MemoryGame.cs", "", null,
                        ignoreUnindentedLines: false
                    ).KoVisible(showingMemoryGameSrc).WithAttr("style", "height: 20em"),
                    FileFragmentFigure(
                        Group(Em("Memory Game"), " web page generated by", Spanner, "."),
                        Lang.markup, Path.Combine(Const.DemoWebSitePath, "html", "MemoryGame.html"), "", null,
                        ignoreUnindentedLines: false,
                        filter: StripSpannerRuntimeFilter
                    ).KoVisible(!showingMemoryGameSrc).WithAttr("style", "height: 20em")
                )
            );

            sections.Add(
                Section("Overview", "Overview",
                    P(Spanner, " is a C# solution to the tedious problems faced by single-page ",
                    "web application developers.  The design goal was to provide programmers with a ",
                    "highly protective, single, expressive, lightweight, statically typed coding ",
                    "environment allowing them to exploit their existing knowledge of HTML, JavaScript, ",
                    "and ", Knockout, "."),
                    Subsection("What is hard about conventional web app development?",
                        P("Standard web technologies, namely HTML, CSS, and JavaScript, have evolved in a ",
                        "piecemeal fashion largely untouched by any knowledge of computer science. ",
                        "The result is an unfortunate polyglot ",
                        "which places demands on the programmer which much of mainstream software development ",
                        "left behind a long time ago:"),
                        UL(
                            LI(B("'Stringly typed' programming. "), "A web application integrates code written ",
                            "in HTML, CSS, and JavaScript.  Identifiers are shared across the three languages ",
                            "purely as embedded strings.  Current tools provide at best rudimentary protection ",
                            "against typos.  Protection against inappropriate use, such as type errors, and ",
                            "support for basic refactoring is essentially non-existent."),
                            LI(B("JavaScript is effectively untyped. "), "Yes, JavaScript has a type system of ",
                            "sorts and, yes, ", TypeScript, " goes some way to remedying that problem, but ",
                            "in almost all circumstances the programmer only finds out about type errors ",
                            "when the application misbehaves or crashes (with ", TypeScript, " these problems ",
                            "still arise due to the ", Code("any"), " type and the unchecked embedding of names as ",
                            "strings in HTML and CSS).  In modern languages, such as C#, ",
                            "such errors are flagged ", Em("as you type"), " by the development environment."),
                            LI(B("Poor abstraction support. "), "In a mainstream language we just define ",
                            "functions to abstract over common operations.  There is no single, simple, ",
                            "equivalent abstraction mechanism for HTML or CSS without resorting to ",
                            "mutually ignorant tools such as ", Em("razor"), " and ", Em("less"), " and ",
                            "no mechanisms which integrate across all three web languages."),
                            LI(B("Debugging is tedious.  Trivial errors go undetected before runtime. "),
                            "A great deal of a web developer's time is spent tracking down trivial bugs ",
                            "which would have been caught automatically in any other modern programming domain.")
                        )
                    ),
                    Subsection("Why Spanner?",
                        P(Spanner, " addresses these problems by providing a lightweight, embedded ",
                        "domain specific language in C#.  Every HTML element, ", Knockout, " binding, ",
                        "and JavaScript type and control-flow statement has a corresponding ", Spanner, " ",
                        "function with the same name and meaning. ", Spanner, " understands ordinary C# POCOs ",
                        "which allows for seamless integration with server-side APIs. ", Spanner, " also ",
                        "integrates well with third party JavaScript libraries.  Because ", Spanner, " does not ",
                        "force a policy on the developer (it is not a 'framework' in that sense), you are free ",
                        "to develop web applications in whatever style suits your needs.  Because a ",
                        Spanner, " solution is a C# program, the developer has the full benefit of working in a ",
                        "single, modern, integrated, statically typed language.  Finally, HTML and JavaScript ",
                        "generated by ", Spanner, " is both easy to read and debug and maps directly ",
                        "on to the original C# code, right down to the variable names.")
                    )
                )
            );

            sections.Add(
                Section("Download", "Download",
                    P("You can download ", Spanner, " from ",
                    A(Code("spanner.codeplex.com ")).WithAttr("href", "http://spanner.codeplex.com"), ". ",
                    "It is released under a ", A("variant of the Microsoft Public Licence").WithAttr("href",
                    "https://spanner.codeplex.com/SourceControl/latest#Spanner/LICENCE.txt"), ", which means ",
                    "you are free to use this code without restriction, in commercial software or otherwise, ",
                    "provided only you retain the original licence for ", Spanner, ".")
                )
            );

            TheChapter = CommonUI.Chapter("Home", "Home", sections, initActs);
        }
    }
}
